// ActionScript file
import COMPONENTS.twDemandSheetPrint;
import COMPONENTS.twDropReason;
import COMPONENTS.twExpensePrint;
import COMPONENTS.twProfitLossPrint;
import COMPONENTS.twRidersBill;

import ENUMS.ApplicationVariables;

import EVENTS.CloseWithReasonEvent;
import EVENTS.GridActionClicked;

import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.filesystem.File;
import flash.net.FileFilter;
import flash.ui.Keyboard;
import flash.utils.Dictionary;

import mx.collections.HierarchicalData;
import mx.controls.Alert;
import mx.controls.TextInput;
import mx.events.AdvancedDataGridEvent;
import mx.events.CloseEvent;
import mx.events.DataGridEvent;
import mx.events.DataGridEventReason;
import mx.events.IndexChangedEvent;
import mx.events.ItemClickEvent;
import mx.events.ListEvent;
import mx.managers.PopUpManager;
import mx.utils.StringUtil;

import org.flexlancer.Logger.Logger;
import org.flexlancer.databases.AppUsers;
import org.flexlancer.databases.Bill;
import org.flexlancer.databases.DatabaseManager;
import org.flexlancer.databases.DemandSheet;
import org.flexlancer.databases.DemandSheetItems;
import org.flexlancer.databases.DropBillReasons;
import org.flexlancer.databases.ExpenseType;
import org.flexlancer.databases.Expenses;
import org.flexlancer.databases.ResetBill;
import org.flexlancer.enums.BillType;
import org.flexlancer.utils.CacheUtils;
import org.flexlancer.utils.DateTimeUtils;
import org.flexlancer.utils.FormatingUtils;

[Bindable]
private var dpSales:Array;
[Bindable]
private var dpResetBills:Array;
[Bindable]
private var dpProductSales:HierarchicalData;
[Bindable]
private var dpWaiterSales:XMLList;
[Bindable]
private var dpDeliverySales:Array;
[Bindable]
private var dpDiscountedSales:Array;
[Bindable]
private var dpCreditSales:HierarchicalData;

[Bindable]
private var dpDroppedBills:Array;
[Bindable]
private var dpServiceCharges:Array;

[Bindable]
private var resetbillcount_label:String = "";

[Bindable]
private var dropbillcount_label:String = "";
[Bindable]
private var discountcount_label:String = "";
[Bindable]
private var deliverybillcount_label:String = "";
[Bindable]
private var servicechargestotal_label:String = "";

[Bindable]
private var gtotal_label:String = "";
[Bindable]
private var deliverytotal_label:String = "";
[Bindable]
private var discounttotal_label:String = "";

private var completeDeliveryBills:Array;

private var completeDiscountedSales:Array;

private var dbFile:File = new File();

private function OnLoad():void{
	try{
		Logger.log_file_name = "REPORTS.log";
		Logger.Log("===================================================================");
		Logger.Log("REPORTS application loads");
		Logger.Log("===================================================================");
		this.maximize();
		this.txtUserID.setFocus();
		this.dbFile.addEventListener(Event.SELECT,OnSelectDBFile);
		//this.LoadData();
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function OnSelectDBFile(evt:Event):void{
	try{
		Logger.Log("DB selected: " + this.dbFile.nativePath);
		lblFileName.text = "File selected: "+this.dbFile.nativePath;
		DatabaseManager.fileDB = this.dbFile;
		//Logger.Log("Going for load data");
		//this.LoadData();
		//Logger.Log("Data loaded successfully");
	}catch(err:Error){
		Logger.LogE(err);
	}
}
private function OnLoadDB():void{
	try{
		Logger.Log("LoadDB Clicked");
		this.dbFile.browseForOpen("Open Database file",[new FileFilter("Database File","*.db")]);
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private var DatesMode:String = "ALL";
private var dispDate:Date;
private const MS_A_DAY:Number = 24 * 60 * 60 * 1000;
private const MS_A_WEEK:Number = 7 * 24 * 60 * 60 * 1000;

private function SetDatesWithMode(parmStarting:Date):void{
	try{
		this.dispDate = parmStarting;
		
		var dtNow:Date = parmStarting;
		var dtFrom:Date;
		var dtTo:Date;
		 
		switch(this.DatesMode.toUpperCase()){
			case "DAILY":
				dtFrom = dtNow;
				dtTo = dtNow;
			break;
			
			case "WEEKLY":
				dtFrom = new Date(dtNow);
				//dtFrom.setTime(dtFrom.getTime() - dtFrom.day * this.MS_A_DAY );
				//dtFrom.setTime(dtFrom.getTime() + this.MS_A_DAY );

				dtTo = new Date(dtNow);
				dtTo.setTime(dtTo.getTime() + 6 * this.MS_A_DAY );
				
				while( dtTo.month != dtFrom.month ){
					dtTo.setTime(dtTo.getTime() - this.MS_A_DAY );
				}
			break;
			
			case "MONTHLY":
				dtFrom = new Date(dtNow);
				dtFrom.setTime(dtFrom.getTime()-(dtFrom.date-1)*this.MS_A_DAY);
				
				dtTo = new Date(dtNow);
				var next:Date = new Date(dtTo);
				
				do{
					dtTo.setTime(next.getTime());
					next.setTime(dtTo.getTime() + this.MS_A_DAY);
				}while ( dtTo.month == next.month );
				
			break;
			default:
				dtFrom = new Date();
				dtTo = new Date();
			break;
		}
		
		this.dfFromDate.selectedDate = dtFrom;
		this.dfToDate.selectedDate = dtTo;
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function OnNextDate():void{
	try{
		var newDate:Date = new Date;
		
		switch(this.DatesMode.toUpperCase()){
			case "DAILY":
				newDate.setTime(this.dispDate.getTime()+this.MS_A_DAY);
			break;
			
			case "WEEKLY":
				newDate.setTime(this.dfToDate.selectedDate.getTime()+this.MS_A_DAY);
			break;
			
			case "MONTHLY":
				newDate.setTime(this.dispDate.getTime());
				var mon:Number = newDate.month;
				while ( mon == newDate.month ) newDate.setTime(newDate.getTime()+this.MS_A_DAY);
			break;
		}
		
		this.SetDatesWithMode(newDate);
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function OnPrevDate():void{
	try{
		var newDate:Date = new Date;
		
		switch(this.DatesMode.toUpperCase()){
			case "DAILY":
				newDate.setTime(this.dispDate.getTime()-this.MS_A_DAY);
			break;
			
			case "WEEKLY":
				newDate.setTime(this.dfFromDate.selectedDate.getTime()-this.MS_A_WEEK);
			break;
			
			case "MONTHLY":
				newDate.setTime(this.dispDate.getTime());
				var mon:Number = newDate.month;
				while ( mon == newDate.month ) newDate.setTime(newDate.getTime()-this.MS_A_DAY);
			break;
		}
		
		this.SetDatesWithMode(newDate);
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function OnDateTypeItemClicked(evt:ItemClickEvent):void{
	try{
		var strVal:String = evt.currentTarget.selectedValue;
		this.DatesMode = strVal.toUpperCase();
		
		this.dfFromDate.enabled = true;
		this.dfToDate.enabled = true;
		var pDate:Date = DateTimeUtils.TodayCutOffDate;
		switch(strVal.toUpperCase()){
			case "ALL":
				this.dfFromDate.enabled = false;
				this.dfToDate.enabled = false;
			break;
			case "WEEKLY":
				pDate.date = 1;
			break;
		}
		
		this.SetDatesWithMode(pDate);
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function MakeCondition():String{
	try{
		var retValue:String = "";
		
		if ( this.chkDineIn.selected ){
			retValue = "'"+BillType.DINE_IN+"'"
		}
		
		if ( this.chkTakeAway.selected ) {
			if ( retValue != "" ) retValue +=",";
			retValue += "'"+BillType.TAKE_AWAY+"'";
		}
		
		if ( this.chkDelivery.selected ) {
			if ( retValue != "" ) retValue +=",";
			retValue += "'"+BillType.DELIVERY+"'";
		}
		
		//retValue = "billcategory IN ("+retValue+") AND (billstatus IS NULL OR billstatus LIKE 'PAID')";
		retValue = "billcategory IN ("+retValue+")";
		
		if ( this.dfFromDate.enabled && this.dfToDate.enabled ) {
			var dateFrom:String = DateTimeUtils.ToStandardDate(this.dfFromDate.selectedDate);
			var dateTo:String = DateTimeUtils.ToStandardDate(this.dfToDate.selectedDate);
			retValue  += " AND billdate BETWEEN '"+dateFrom+"' AND '"+dateTo+"'";
		}
		return retValue;
	}catch(err:Error){
		throw err;
	}
	return "";
}
private function LoadData():void{
	try{
		Logger.Log("Loading Data from database");
		var arr:Array = Bill.List(this.MakeCondition());
		Logger.Log("Initializing report variables");
		
		var hashSC:Dictionary = new Dictionary();
		
		this.dpSales = new Array;
		this.dpDeliverySales = new Array;
		this.dpDroppedBills = new Array;
		this.dpServiceCharges = new Array;
		this.dpDiscountedSales = new Array;
		this.dpBreakUp = new Array;
		this.dpResetBills = ResetBill.List(this.MakeCondition());
		this.completeDeliveryBills = new Array;
		this.completeDiscountedSales = new Array;
		
		this.lblQT.text = "QT#";
		this.lblSubTotal.text="Total:";
		
		var gtotal:Number = 0;
		var dtotal:Number = 0;
		var distotal:Number = 0;
		
		Logger.Log("Generating data for PAID bills");
		
		for each ( var sitem:Object in arr ){
			if ( sitem.billstatus == "" || sitem.billstatus == "PAID" ){

				if ( sitem.haveservicecharges == 1 ){
					sitem.total -= sitem.servicecharges;
					if ( hashSC[sitem.server] == undefined )
						hashSC[sitem.server] = 0;
					hashSC[sitem.server] += sitem.servicecharges;
				}
				
				if ( sitem.havediscount == 1 ){
					sitem.beforediscount = sitem.total + sitem.discount;
					this.dpDiscountedSales.push(sitem);
					this.completeDiscountedSales.push(sitem);
					distotal += sitem.discount;
				}
				gtotal += sitem.total;
				this.dpSales.push(sitem);
				
				if ( sitem.billcategory == "DELIVERY" ){
					this.dpDeliverySales.push(sitem);
					this.completeDeliveryBills.push(sitem);
					dtotal += sitem.total;
				}
			}else{
				this.dpDroppedBills.push(sitem);
			}
		}
		
		var key:String;
		var sctotal:Number = 0;
		
		for ( key in hashSC ){
			sctotal += hashSC[key];
			this.dpServiceCharges.push({server:key , total:hashSC[key]});
		}
		//Alert.show(FormatingUtils.ToCurrency(10001000));
		this.servicechargestotal_label = "Grand Total: "+FormatingUtils.ToCurrency(sctotal)+"/-";
		this.deliverytotal_label = "Grand Total: "+FormatingUtils.ToCurrency(dtotal)+"/-";
		this.discounttotal_label = "Total Discount: "+FormatingUtils.ToCurrency(distotal)+"/-";
		
		this.deliverybillcount_label = "["+this.dpDeliverySales.length.toString()+" Record(s) found.]";
		this.lblMainCount.text = "["+this.dpSales.length.toString()+" Record(s) found.]";
		this.dropbillcount_label = "["+this.dpDroppedBills.length.toString()+" Record(s) found.]";
		this.resetbillcount_label = "["+this.dpResetBills.length.toString()+" Record(s) found.]";
		this.discountcount_label = "["+this.dpDiscountedSales.length.toString()+" Record(s) found.]";
		
		this.gtotal_label = "Grand Total: "+FormatingUtils.ToCurrency(gtotal)+"/-";
		//this.dgSales.dataProvider = arr;
		
		Logger.Log("Making Product Sales Report");		
		this.MakeProductSalesReportData(this.dpSales);
		Logger.Log("Making Waiter Sales Report");
		this.MakeWaiterSalesReportData(this.dpSales);
		
		this.callLater(this.UpdateUISalesReportWithLatest);
		this.callLater(this.UpdateUIProductsReportWithLatest);
		this.callLater(this.UpdateUIDeliveryReportWithLatest);
		
		/// --------- Management Data
		
		this.MakeCreditSales(this.dpDroppedBills,DropBillReasons.List());
	}catch(err:Error){
		Logger.LogE(err);
	}
}
private function MakeCreditSales(dropBills:Array,dropReasons:Array):void{
	try{
		var hash:Dictionary = new Dictionary;
		for each ( var sReason:Object in dropReasons ){
			if ( sReason.iscredit == 1 ){
				hash[sReason.reason] = new Object;
				hash[sReason.reason].billid = sReason.reason;
				hash[sReason.reason].total = 0;
				hash[sReason.reason].children = new Array;
			}
		} 
		
		for each ( var sBill:Object in dropBills ){
			if ( hash[sBill.statusreason] != undefined ){
				hash[sBill.statusreason].total += sBill.total;
				hash[sBill.statusreason].children.push(sBill);
			}
		}
		
		var arr:Array = new Array;
		var key:String = "";
		
		for ( key in hash ){
			hash[key].billid += " ("+hash[key].children.length+")";
			arr.push(hash[key]);
		}
		this.dpCreditSales = new HierarchicalData(arr);
	}catch(err:Error){
		Logger.LogE(err);
	}
}
private function OnTabChanged(evt:IndexChangedEvent):void{
	try{
		switch(evt.newIndex){
			case 0:
				this.callLater(this.UpdateUISalesReportWithLatest);
				break;
			case 1:
				this.callLater(this.UpdateUIProductsReportWithLatest);
				break;
			case 2:
				this.callLater(this.UpdateUIDeliveryReportWithLatest);
				break;
		}
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function UpdateUIDeliveryReportWithLatest():void{
	try{
		if ( this.dgDeliveryOrders != null ){
			this.dgDeliveryOrders.verticalScrollPosition = this.dgDeliveryOrders.maxVerticalScrollPosition;
		}
	}catch(err:Error){
		Logger.LogE(err);
	}
}
private function UpdateUISalesReportWithLatest():void{
	try{
		if ( this.dgSales != null ){
			this.dgSales.verticalScrollPosition = this.dgSales.maxVerticalScrollPosition;
		}
	}catch(err:Error){
		Logger.LogE(err);
	}
}
private function UpdateUIProductsReportWithLatest():void{
	try{
		if ( this.adgProductReport != null ){
			this.adgProductReport.expandAll();
		}
	}catch(err:Error){
		Logger.LogE(err);
	}
}
private function MakeProductSalesReportData(parmArr:Array):void{
	try{
		CacheUtils.ReadCache(this.breakup_rates ,ApplicationVariables.BREAK_UP_CACHE);
		
		var xmlComplete:XML = new XML(<CompleteProductSales />);
		var dictCategories:Dictionary = new Dictionary();
		
		for each ( var singleItem:Object in parmArr ){
			//var details:Array = BillItems.List("billrefid="+singleItem.billid);
			for each ( var singleDetail:Object in singleItem.items ){
				var cat:String = singleDetail.itemcat;
				var title:String = singleDetail.title;
				
				if ( dictCategories[cat] == null ){
					dictCategories[cat] = new Dictionary();
				}
				var dictCat:Dictionary = dictCategories[cat];
				
				if ( dictCat[title] == null ){
					var insert:Object = new Object();
					insert.count = 0;
					insert.total = 0;
					dictCat[title] = insert;
				}
				
				dictCat[title].count += singleDetail.quantity;
				dictCat[title].total += singleDetail.total;
			}
		}
		
		var catkey:String = "";
		for ( catkey in dictCategories ){
			var titlekey:String = "";
			var dictP:Dictionary = dictCategories[catkey];
			var catxml:XML = new XML("<Category isBranch='true' title=\""+catkey+"\" />");
			var count_total:Number = 0;
			var g_total:Number = 0;
			
			for ( titlekey in dictP ){
				count_total += dictP[titlekey].count;
				g_total += dictP[titlekey].total;
				var itemxml:XML = new XML("<Item title=\""+titlekey+"\" count='"+dictP[titlekey].count+"' total='"+dictP[titlekey].total+"' />");
				catxml.appendChild(itemxml);
				
				var breakup_item:Object = new Object();
				breakup_item.heads = titlekey.toUpperCase();
				breakup_item.qty = dictP[titlekey].count;
				breakup_item.rate = this.breakup_rates[breakup_item.heads] == undefined ? 0 : this.breakup_rates[breakup_item.heads];
				breakup_item.total = breakup_item.qty * breakup_item.rate;
				this.dpBreakUp.push(breakup_item);
			} 
			
			catxml.@count = count_total;
			catxml.@total = g_total;
			xmlComplete.appendChild(catxml);
			/*
			var breakup_item:Object = new Object();
			breakup_item.heads = catkey;
			breakup_item.qty = count_total;
			breakup_item.rate = 0;
			breakup_item.total = 0;
			this.dpBreakUp.push(breakup_item);
			*/ 
		}
		
		this.dpBreakUp.sortOn("heads");
		this.CalculateBreakUpTotal();
		this.dpProductSales = new HierarchicalData(xmlComplete.children());
	}catch(err:Error){
		Logger.LogE(err);
	}
}
private function MakeWaiterSalesReportData(parmArr:Array):void{
	try{
		var xmlComplete:XML = new XML(<CompleteWaiterSales />);
		var dictWaiter:Dictionary = new Dictionary();
		
		for each ( var singleItem:Object in parmArr ){
			var waiter:String = singleItem.server;
			if ( dictWaiter[waiter] == null ){
				dictWaiter[waiter] = new Object();
				dictWaiter[waiter].title = waiter;
				dictWaiter[waiter].total = 0;
			}
			var obj:Object = dictWaiter[waiter];
			obj.total += singleItem.total;
		}
		
		var waiterkey:String = "";
		for ( waiterkey in dictWaiter ){
			var waiterXml:XML = new XML("<Server title='"+waiterkey+"' total='"+dictWaiter[waiterkey].total+"' />");
			xmlComplete.appendChild(waiterXml);
		}
		
		this.dpWaiterSales = xmlComplete.children();
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function dgSales_OnCreationComplete():void{
	try{
		if ( !this.dgSales.hasEventListener(GridActionClicked.GRID_ITEM_DROP_BILL) ){
			this.dgSales.addEventListener(GridActionClicked.GRID_ITEM_DROP_BILL,this.dgSales_OnDropBill);
		}
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function dgSales_OnDropBill(evt:GridActionClicked):void{
	try{
		var dropres:twDropReason = PopUpManager.createPopUp(this,twDropReason,true) as twDropReason;
		dropres.addEventListener(CloseWithReasonEvent.DROP_WITH_REASON,OnDropBillConfirmation);
		PopUpManager.centerPopUp(dropres);
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function OnDropBillConfirmation(evt:CloseWithReasonEvent):void{
	try{
		if ( evt.detail == Alert.YES ){
			//this.BillDroped(evt.reason);
			Bill.DropBill(this.dgSales.selectedItem.billid,evt.reason);
			this.LoadData();
		}
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function dgSales_OnItemClicked(evt:ListEvent):void{
	try{
		this.dgDetails.dataProvider = this.dgSales.selectedItem.items;//BillItems.List("billrefid="+this.dgSales.selectedItem.billid);
		this.lblQT.text = "QT#: "+ this.dgSales.selectedItem.billid;
		this.lblSubTotal.text = "Total: "+this.dgSales.selectedItem.total;
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function dgDelivery_OnChange():void{
	try{
		if ( this.dgDeliveryOrders.selectedItem != null ){
			this.dgDeliveryDetails.dataProvider = this.dgDeliveryOrders.selectedItem.items;//BillItems.List("billrefid="+this.dgDeliveryOrders.selectedItem.billid);
		}
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function dgResetBill_OnItemClicked(evt:ListEvent):void{
	try{
		this.dgResetDetails.dataProvider = this.dgResetBill.selectedItem.items;//BillItems.List("billrefid="+this.dgSales.selectedItem.billid);
	}catch(err:Error){
		Logger.LogE(err);
	}
}

/*
===============================================================================================
===============================================================================================
                      CREDIT SALES SCRIPTS
===============================================================================================
===============================================================================================
*/

private function dgCreditSales_OnChange():void{
	try{
		if ( this.adgCreditSales.selectedItem != null ){
			this.dgCreditHeadDetails.dataProvider = this.adgCreditSales.selectedItem.items;//BillItems.List("billrefid="+this.dgDeliveryOrders.selectedItem.billid);
		}
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function adgCreditSales_OnCC():void{
	try{
		if ( !this.adgCreditSales.hasEventListener(GridActionClicked.GRID_ITEM_CLEAR_CREDIT_BILL) ){
			this.adgCreditSales.addEventListener(GridActionClicked.GRID_ITEM_CLEAR_CREDIT_BILL,this.adgCreditSales_OnClearBill);
		}
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function adgCreditSales_OnClearBill(evt:GridActionClicked):void{
	try{
		Alert.show("Are you sure to clear this bill?","Confirmation",Alert.YES|Alert.NO,this,this.OnClearBillConfirmation);
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function OnClearBillConfirmation(evt:CloseEvent):void{
	try{
		if ( evt.detail == Alert.YES ){
			//this.BillDroped(evt.reason);
			Bill.ClearBill(this.adgCreditSales.selectedItem.billid);
			this.LoadData();
		}
	}catch(err:Error){
		Logger.LogE(err);
	}
}

/*
===============================================================================================
===============================================================================================
                      DISCOUNT SALES SCRIPTS
===============================================================================================
===============================================================================================
*/

private function OnDiscountSearchFilterChange():void{
	try{
		this.dpDiscountedSales = new Array;
		var dsn:String = StringUtil.trim(this.txtDiscountSearchNote.text);
		var total:Number = 0;
		
		for each ( var sitem:Object in this.completeDiscountedSales ){
			if ( dsn != "" ){
				if ( sitem.discountnotes.toString().indexOf(dsn) < 0 ){
					continue;
				}
			}
			total += sitem.total;
			this.dpDiscountedSales.push(sitem);
		} 
		this.discounttotal_label = "Total Discount: "+total.toString()+"/-";
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function dgDiscount_OnChange():void{
	try{
		if ( this.dgDiscountedSales.selectedItem != null ){
			this.dgDiscountedDetails.dataProvider = this.dgDiscountedSales.selectedItem.items;//BillItems.List("billrefid="+this.dgDeliveryOrders.selectedItem.billid);
		}
	}catch(err:Error){
		Logger.LogE(err);
	}
}

/*
===============================================================================================
===============================================================================================
                      DROPPED BILL SCRIPTS
===============================================================================================
===============================================================================================
*/

private function dgDropped_OnChange():void{
	try{
		if ( this.dgDroppedBills.selectedItem != null ){
			this.dgDropBillDetails.dataProvider = this.dgDroppedBills.selectedItem.items; //BillItems.List("billrefid="+this.dgDroppedBills.selectedItem.billid);
		}
	}catch(err:Error){
		Logger.LogE(err);
	}
}
private function Reports_OnEnter():void{
	try{
		if ( !this.showManage ){
			this.tabnavigator1.removeChild(this.canManage);
		}
	}catch(err:Error){
		Logger.LogE(err);
	}
}
/*
===============================================================================================
===============================================================================================
                      DELIVERY AREA SCRIPTS
===============================================================================================
===============================================================================================
*/


private function OnDeliveryOrdersSearchFilterChange():void{
	try{
		this.dpDeliverySales = new Array;
		var qt:String = StringUtil.trim(this.txtDeliverySearchByQT.text);
		var cn:String = StringUtil.trim(this.txtDeliverySearchByContactNumber.text);
		var addr:String = StringUtil.trim(this.txtDeliverySearchByCustomerAddress.text).toUpperCase();
		var area:String = StringUtil.trim(this.txtDeliverySearchByCustomerArea.text).toUpperCase();
		
		for each ( var sitem:Object in this.completeDeliveryBills ){
			if ( qt != "" ){
				if ( sitem.billid.toString().indexOf(qt) < 0 ){
					continue;
				}
			}
			if ( cn != "" ){
				if ( sitem.customernumber.toString().indexOf(cn) < 0 ){
					continue;
				}
			}
			if ( addr != "" ){
				if ( sitem.customeraddress.toString().indexOf(addr) < 0 ){
					continue;
				}
			}
			if ( area != "" ){
				if ( sitem.customerarea.toString().indexOf(area) < 0 ){
					continue;
				}
			}
			this.dpDeliverySales.push(sitem);
		} 
	}catch(err:Error){
		Logger.LogE(err);
	}
}
private function OnResetFilterDelivery():void{
	try{
		this.txtDeliverySearchByContactNumber.text = "";
		this.txtDeliverySearchByQT.text = "";
		this.txtDeliverySearchByCustomerAddress.text = "";
		this.txtDeliverySearchByCustomerArea.text = "";
		
		this.OnDeliveryOrdersSearchFilterChange();
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function OnPrintRidersBill():void{
	try{
		var twR:twRidersBill = PopUpManager.createPopUp(this,twRidersBill,true) as twRidersBill;
		twR.SetValue(this.completeDeliveryBills);
		PopUpManager.centerPopUp(twR);
		twR.y = 0;
	}catch(err:Error){
		Logger.LogE(err);
	}
}
/*
===============================================================================================
===============================================================================================
                      LOGIN SCRIPTS
===============================================================================================
===============================================================================================
*/
[Bindable]
private var showManage:Boolean = false;
[Bindable]
private var welcome_lbl:String = "";

private function OnLogin():void{
	try{
		var arr:Array = AppUsers.List("userid LIKE '"+this.txtUserID.text+"' AND password LIKE '"+this.txtPassword.text+"'");
		if ( arr.length == 0 ){
			Alert.show("Invalid userid/password combination","Login Error",4,this,LoginFailed);
		}else if ( arr[0].allowreports == 0 ){
			Alert.show("You don't have access to reports. Please contact to administrator.","You are blocked",4,this,LoginFailed);
		}else{
			this.showManage = arr[0].allowmanage == 1 ? true : false;
			this.currentState = "Reports";
			this.welcome_lbl = "Welcome Mr."+arr[0].userid;
		}
	}catch(err:Error){
		Logger.LogE(err);
	}
}
private function LoginFailed(evt:CloseEvent):void{
	this.txtUserID.setFocus();
}

/*
===============================================================================================
===============================================================================================
                      EXPENSES SCRIPTS
===============================================================================================
===============================================================================================
*/
[Bindable]
private var expense_date_lbl:String = (new Date).toDateString();
[Bindable]
private var expense_total_lbl:String = "Expenses Grand Total: 0/-";
[Bindable]
private var dpExpenseType:Array = new Array();
[Bindable]
private var dpTodayExpenses:HierarchicalData;

private function Expense_OnCC():void{
	try{
		this.FetchExpenseReport_OnClick();
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function OnAddExpenseType():void{
	try{
		if ( this.txtExpenseType.text == "" ){
			return;
		}
		
		if ( this.dpExpenseType.indexOf(this.txtExpenseType.text) == -1 ){
			ExpenseType.Add(this.txtExpenseType.text.toUpperCase());
			this.txtExpenseType.text = "";
			this.FetchExpenseReport_OnClick();
		}
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function OnRemoveExpenseType():void{
	try{
		if ( this.adgExpenseBreakUp.selectedItem != null ){
			if ( this.adgExpenseBreakUp.selectedItem.children != undefined ){
				if ( this.adgExpenseBreakUp.selectedItem.children.length == 0 ){
					ExpenseType.Delete("expensetypename LIKE '"+this.adgExpenseBreakUp.selectedItem.item+"'");
					this.FetchExpenseReport_OnClick();
				}else{
					Alert.show("Remove expenses before deleting the expense type");
				}
			}
		}
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function OnAddExpense():void{
	try{
		if ( this.cmbExpenseType.selectedItem == null ){
			Alert.show("Please select Expense Type.");
			return;
		}
		
		if ( this.txtExpenseTotal.text == "" ){
			return;
		}
		
		var sel_cat:String = this.cmbExpenseType.selectedItem as String;

		Expenses.Add(this.txtExpenseTitle.text.toUpperCase(),sel_cat,Number(this.txtExpenseTotal.text),DateTimeUtils.ToStandardDate(this.dcExpenseDate.selectedDate));		
		this.cmbExpenseType.selectedItem = null;
		
		this.txtExpenseTitle.text = "";
		this.txtExpenseTotal.text = "";
		this.cmbExpenseType.setFocus();
		
		this.FetchExpenseReport_OnClick();
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function CalculateExpenseTotal():Number{
	try{
		var gtotal:Number = 0;
		
		for each ( var singleItem:Object in this.dpTodayExpenses.source ){
			gtotal += singleItem.total;
		}
		
		this.expense_total_lbl = "Expenses Total: " + gtotal.toString();
		
		return gtotal;
	}catch(err:Error){
		throw err;
	}
	return 0;
}

private function ExpenseSetToday_OnClick():void{
	try{
		this.dcExpenseDate.selectedDate = new Date();
		this.expense_date_lbl = (new Date).toDateString();
		this.FetchExpenseReport_OnClick();
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function FetchExpenseReport_OnClick():void{
	try{
		this.dpExpenseType = new Array;
		var arr:Array = ExpenseType.List();
		var dpArr:Array = new Array;
		
		for each ( var sobj:Object in arr ){
			this.dpExpenseType.push(sobj.expensetypename);
			dpArr.push({item:sobj.expensetypename,total:0,children:new Array});
		}
		
		var sel_date:Date = this.dcExpenseDate.selectedDate;
		arr = Expenses.List("expdate LIKE '"+DateTimeUtils.ToStandardDate(sel_date)+"'");
		
		for each ( var singleExp:Object in arr ){
			var key:String = singleExp.expcat;
			var found_cat:Boolean = false;
			var found_obj:Object = null;
			for each ( var searchObj:Object in dpArr ){
				if ( searchObj.item == key ){
					found_obj = searchObj;
					found_obj.total += singleExp.expamount;
					break;
				}
			}
			if ( !found_obj ){
				found_obj = {item:key,total:0,children:new Array}
				dpArr.push(found_obj);
			}
			found_obj.children.push({item:singleExp.exptitle , total:singleExp.expamount, id:singleExp.expid});
		}
		
		this.dpTodayExpenses = new HierarchicalData(dpArr);
		this.CalculateExpenseTotal();
		
		this.callLater(this.adgExpenseBreakUp.expandAll);
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function DeleteExpense_OnClick():void{
	try{
		if ( this.adgExpenseBreakUp.selectedItem == null ){
			Alert.show("Please select expense item to delete.");
			return;
		}
		
		var objSel:Object = this.adgExpenseBreakUp.selectedItem;
		
		Expenses.Delete("expid = "+objSel.id);
		this.FetchExpenseReport_OnClick();
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function ResetExpense_OnClick():void{
	try{
		var sel_date:Date = this.dcExpenseDate.selectedDate;
		Expenses.Delete("expdate LIKE '"+sel_date.fullYear+"-"+(sel_date.month+1).toString()+"-"+sel_date.date+"'");
		this.FetchExpenseReport_OnClick();
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function OnSaveExpenseConfirmation(evt:CloseEvent):void{
	try{
		if ( evt.detail == Alert.YES ){
			Alert.show("Expense is saved.");
		}
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function SaveExpense_OnClick():void{
	try{
		Alert.show("Are you sure to save Expenses for the day?","Save Expense Confirmation",Alert.YES | Alert.NO,this,this.OnSaveExpenseConfirmation);
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function OnPrintExpenses():void{
	try{
		var wind:twExpensePrint = PopUpManager.createPopUp(this,twExpensePrint,true) as twExpensePrint;
		PopUpManager.centerPopUp(wind);
		wind.y = 0;
		wind.canPrint.SetPrintData(this.dpTodayExpenses.source as Array,this.dcExpenseDate.selectedDate);
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function OnPrintProfitLoss():void{
	try{
		var wind:twProfitLossPrint = PopUpManager.createPopUp(this,twProfitLossPrint,true) as twProfitLossPrint;
		PopUpManager.centerPopUp(wind);
		wind.y = 0;
		
		//wind.SetPrintData(this.dpTodayExpenses.source as Array,this.dcExpenseDate.selectedDate);
		var dictSales:Dictionary = new Dictionary();
		
		for each ( var singleSale:Object in this.dpSales ){
			if ( dictSales[singleSale.billcategory] == undefined )
				dictSales[singleSale.billcategory] = 0;
				
			dictSales[singleSale.billcategory] += singleSale.total;
		} 
		
		var arrItems:Array = new Array();
		var key:String;
		var net:Number = 0;
		
		for ( key in dictSales ){
			arrItems.push({item:key, total:dictSales[key]});
			net += dictSales[key];
		}
		var exp_total:Number = CalculateExpenseTotal();
		
		arrItems.push({item:"Total Expense",total:exp_total});
		net -= exp_total;
		
		wind.SetPrintData(arrItems,net,this.dcExpenseDate.selectedDate);
	}catch(err:Error){
		Logger.LogE(err);
	}
}
/*
===============================================================================================
===============================================================================================
                      BREAK UP SCRIPTS
===============================================================================================
===============================================================================================
*/
[Bindable]
private var breakup_rates:Dictionary = new Dictionary;
[Bindable]
private var dpBreakUp:Array;
[Bindable]
private var breakup_total:String = "TOTAL: 0";

private function dgBreakUp_OnItemEditEnd(evt:DataGridEvent):void{
	try{
		if ( evt.reason == DataGridEventReason.NEW_ROW ) {
			var sel_item:Object = this.dgBreakUp.selectedItem;
			var myEditor:TextInput = TextInput(evt.currentTarget.itemEditorInstance);
			var newVal:Number = Number(myEditor.text);
			if ( isNaN(newVal) ) newVal = sel_item.rate;
			sel_item.rate = newVal;
			this.breakup_rates[this.dgBreakUp.selectedItem.heads] = newVal;
			sel_item.total = sel_item.qty * sel_item.rate;
			this.CalculateBreakUpTotal();
		}
		CacheUtils.WriteCache(this.breakup_rates,ApplicationVariables.BREAK_UP_CACHE);
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function dgBrakUp_OnKeyUp(evt:KeyboardEvent):void{
	try{
		if ( evt.keyCode == Keyboard.ENTER ){
			//this.dgBreakUp.editedItemPosition = {rowIndex:2,colIndex:2};
		}
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function btnResetBreakUp_OnClick():void{
	try{
		for each ( var sItem:Object in this.dpBreakUp ){
			sItem.rate = 0;
			sItem.total = 0;
		}
		this.CalculateBreakUpTotal();
		this.dgBreakUp.dataProvider = this.dpBreakUp;
		this.breakup_rates = new Dictionary;
		CacheUtils.WriteCache(this.breakup_rates,ApplicationVariables.BREAK_UP_CACHE);
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function CalculateBreakUpTotal():void{
	try{
		var total:Number = 0 ;
		for each ( var sItem:Object in this.dpBreakUp ){
			total += sItem.total;
		}
		this.breakup_total = "TOTAL: "+total.toString();
	}catch(err:Error){
		Logger.LogE(err);
	}
}

/*
===============================================================================================
===============================================================================================
                      DEMAND SHEET SCRIPTS
===============================================================================================
===============================================================================================
*/

[Bindable]
private var dpDemandSheet:HierarchicalData;

private function DemandSheet_OnCC():void{
	try{
		var xml:XML = new XML(DemandSheetItems.ListInXML());
		var srno:int = 1;
		var arrDP:Array = new Array();
		
		for each ( var cat:XML in xml.children() ){
			var objCategory:Object = new Object;
			objCategory.title = cat.@title.toString();
			objCategory.children = new Array;
			objCategory.id = String(cat.@id);
			
			var ref_arr:Array = objCategory.children;
			
			for each ( var singleItem:XML in cat.children() ){
				var objItem:Object = new Object;
				
				objItem.id = String(singleItem.@id);
				objItem.parentid = String(cat.@id);
				objItem.category = String(cat.@title);
				objItem.displaytitle = srno.toString()+". "+singleItem.@title.toString();
				objItem.title = singleItem.@title.toString();
				
				objItem.openingbalance = 0;
				objItem.demand = 0;
				objItem.issue = 0;
				objItem.total = 0;
				objItem.used = 0;
				objItem.closingbalance = 0;
				
				ref_arr.push(objItem);
				srno++;
			}
			arrDP.push(objCategory);
		}
		this.dpDemandSheet = new HierarchicalData(arrDP);
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function DemandSheet_OnReset():void{
	try{
		var arr_source:Array = this.dpDemandSheet.source as Array
		for each ( var cat:Object in arr_source ){
			for each ( var item:Object in  cat.children ){
				item.openingbalance = 0;
				item.demand = 0;
				item.issue = 0;
				item.total = 0;
				item.used = 0;
				item.closingbalance = 0;
			}
		}
		this.dpDemandSheet = new HierarchicalData(arr_source);
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function DemandSheet_OnAddItem():void{
	try{
		if ( this.txtDemandSheetItemName.text == "" ){
			Alert.show("Please Enter Item name");
			return;
		}
		
		if ( this.adgDemandSheet.selectedItem == null ){
			Alert.show("Pleae select the head where you want to add the item");
			return;
		}
		
		if ( this.adgDemandSheet.selectedItem.children == undefined ){
			Alert.show("Please select the valid head item");
			return;
		}
		
		DemandSheetItems.Add(this.txtDemandSheetItemName.text.toUpperCase(),this.adgDemandSheet.selectedItem.id );
		this.txtDemandSheetItemName.text = "";
		this.DemandSheet_OnCC();
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function DemandSheet_OnAddItemHead():void{
	try{
		if ( this.txtDemandSheetItemName.text == "" ){
			Alert.show("Please Enter Item name");
			return;
		}
		
		DemandSheetItems.Add(this.txtDemandSheetItemName.text.toUpperCase(),-1);
		this.txtDemandSheetItemName.text = "";
		this.DemandSheet_OnCC();		
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function DemandSheet_OnDeleteItem():void{
	try{
		if ( this.adgDemandSheet.selectedItem == null ){
			Alert.show("Pleae select the item which you want to delete");
			return;
		}
		
		DemandSheetItems.Delete("demandsheetitemid = "+this.adgDemandSheet.selectedItem.id);
		this.DemandSheet_OnCC();
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function DemandSheet_OnFetchReport():void{
	try{
		var sel_date:Date = this.dtpDemandSheetDate.selectedDate
		var res:Array = DemandSheet.List("entrydate LIKE '"+DateTimeUtils.ToStandardDate(sel_date)+"'");
		var cat:Object = null;
		var item:Object = null;
		var index:Number = 0;
		var onlynames:Array = new Array;
		var obj:Object = null; 
		var arr_source:Array = this.dpDemandSheet.source as Array
		
		if ( res.length == 0 ) {
			var yesterday:Date = new Date();
			yesterday.setTime( sel_date.getTime() - 24 * 60 * 60 * 1000 );
			
			res = DemandSheet.List("entrydate LIKE '"+DateTimeUtils.ToStandardDate(yesterday)+"'");

			for each ( obj in res ){
				onlynames.push(obj.title);
			}
			
			for each ( cat in arr_source ){
				for each ( item in cat.children ){
					index = onlynames.indexOf(item.title);
					if ( index > -1 ) {
						item.openingbalance = res[index].closingbalance;
						item.demand = 0;
						item.issue = 0;
						item.total = res[index].closingbalance;
						item.used = 0;
						item.closingbalance = res[index].closingbalance;
					}
				}
			}
			this.dpDemandSheet = new HierarchicalData(arr_source);
			return;
		}
		
		for each ( obj in res ){
			onlynames.push(obj.title);
		}
		
		for each ( cat in arr_source ){
			for each ( item in  cat.children ){
				index = onlynames.indexOf(item.title);
				if ( index > -1 ) {
					item.openingbalance = res[index].openingbalance;
					item.demand = res[index].demand;
					item.issue = res[index].issue;
					item.total = res[index].total;
					item.used = res[index].used;
					item.closingbalance = res[index].closingbalance;
				}
			}
		}
		this.dpDemandSheet = new HierarchicalData(arr_source);
		
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function DemandSheet_OnSaveReport():void{
	try{
		Alert.show("Are you sure to save today's Demand sheet?","Save Confirmation",Alert.YES|Alert.NO,this,this.DemandSheet_OnSaveReportConfirmation);
	}catch(err:Error){
		Logger.LogE(err);
		DatabaseManager.Manager.Rollback();
	}
}

private function DemandSheet_OnSaveReportConfirmation(evt:CloseEvent):void{
	try{
		if ( evt.detail == Alert.YES ){
			var sel_date:Date = this.dtpDemandSheetDate.selectedDate
			DatabaseManager.Manager.Begin();
			DemandSheet.Delete("entrydate LIKE '"+DateTimeUtils.ToStandardDate(sel_date)+"'")
			var arr_source:Array = this.dpDemandSheet.source as Array
			for each ( var cat:Object in arr_source ){
				for each ( var item:Object in  cat.children ){
					DemandSheet.Add(DateTimeUtils.ToStandardDate(sel_date),item.title,item.category,item.openingbalance,item.demand,item.issue,item.total,item.used,item.closingbalance);
				}
			}
			DatabaseManager.Manager.Commit();
			CacheUtils.WriteCache(new Array,ApplicationVariables.DEMAND_SHEET_CACHE);
			Alert.show("Demand sheet saved successfully.");
		}
	}catch(err:Error){
		Logger.LogE(err);
		DatabaseManager.Manager.Rollback();
	}
}

private function DemandSheet_OnSetToday():void{
	try{
		this.dtpDemandSheetDate.selectedDate = new Date();
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function DemandSheet_OnPrint():void{
	try{
		var wind:twDemandSheetPrint = PopUpManager.createPopUp(this,twDemandSheetPrint,true) as twDemandSheetPrint;
		PopUpManager.centerPopUp(wind);
		wind.y = 0;
		wind.canPrint.SetPrintData(this.dpDemandSheet.source as Array,this.dtpDemandSheetDate.selectedDate);
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function DemandSheet_OnOpenAll():void{
	try{
		this.adgDemandSheet.expandAll();
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function DemandSheet_OnCloseAll():void{
	try{
		for each ( var obj:Object in this.dpDemandSheet.source ){
			this.adgDemandSheet.expandItem(obj,false);
		}
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function DemandSheet_OnItemEditEnd(evt:AdvancedDataGridEvent):void{
	try{
		if ( evt.reason == DataGridEventReason.NEW_ROW ) {
			var sel_item:Object = this.adgDemandSheet.selectedItem;
			var myEditor:TextInput = TextInput(evt.currentTarget.itemEditorInstance);
			var newVal:Number = Number(myEditor.text);
			
			if ( ! isNaN(newVal) ){
				sel_item[evt.dataField] = newVal;
			}
			sel_item.total = Number(sel_item.openingbalance) + Number(sel_item.issue);
			sel_item.closingbalance = Number(sel_item.total) - Number(sel_item.used);
			this.adgDemandSheet.dataProvider = this.dpDemandSheet; 
		}		
	}catch(err:Error){
		Logger.LogE(err);
	}
}

private function DemandSheet_OnSetOpeningBalance():void{
	try{
		var dtYesterday:Date = DateTimeUtils.TodayCutOffDate;
		dtYesterday.setTime( dtYesterday.getTime() - 24 * 60 * 60 * 1000 );
		var res:Array = DemandSheet.List("entrydate LIKE '"+DateTimeUtils.ToStandardDate(dtYesterday)+"'");
		
		if ( res.length == 0 ) return;
		
		var onlynames:Array = new Array;
		for each ( var obj:Object in res ){
			onlynames.push(obj.title);
		}
		
		var arr_source:Array = this.dpDemandSheet.source as Array
		for each ( var cat:Object in arr_source ){
			for each ( var item:Object in  cat.children ){
				var index:Number = onlynames.indexOf(item.title);
				if ( index > -1 ) {
					item.openingbalance = res[index].closingbalance;
				}
			}
		}
		this.dpDemandSheet = new HierarchicalData(arr_source);
	}catch(err:Error){
		Logger.LogE(err);
	}
}
